﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lesson2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            #region 异常捕获

            Console.WriteLine("异常捕获");
            // 将用户输入的内容存储到 string 类型的变量中
            //string str = Console.ReadLine();

            // parse转字符串为 数值时，必须要合法合规（不能超过范围或汉字）， 如果不合法合规会造成程序卡死
            //int i = int.Parse(str);
            //Console.WriteLine(i);

            // 作用：通过异常捕获 可以避免当 代码报错时 造成的程序卡死
            // 语法：try {} catch {} finally {}
            // 必备部分，需要要的 try catch 成对出现
            try
            {
                // 希望进行异常捕获的代码块  可以放入try中
                // 如果 try中的代码报错了，会跳入catch中
            }
            //catch
            catch(Exception e)
            {
                // try中的程序出错了，会执行 catch 中的代码
                // catch(Exception e) 这个可以跟踪报错的具体信息
            }
            // 可选部分
            finally
            {
                // 最后执行的代码，不管有没有出错都会执行
            }

            #endregion

            #region 算术运算符
            // 赋值符号 =

            // 算术运算符： +、-、*、/、%

            // 浮点型运算，其中一个值要明确加f, 不然都是当成整形计算，结过也是整形
            //float f = 1f / 2; 
            float f = 1 / 2f; 
            Console.WriteLine(f);

            // 默认的整数，是 int 如果用来做除法运算，要注意，会丢失小数点后的小数
            // 如果用浮点数来存储，一定要在 运算时有 浮点数的特征

            // 优先级：乘除取余 优先级高于 加减， 先算乘除取余 后算加减

            // 复合运算符
            // +=  -=  *=  /=  %=

            // 自增 自减运算符
            int a = 1;
            a++;  // 先用再加
            Console.WriteLine(a);

            ++a;  // 先加再用
            Console.WriteLine(a);


            Console.WriteLine(a++);
            Console.WriteLine(++a);


            #endregion

            #region 字符串拼接
            // 字符串用＋号，表示进行字符串拼接
            string str2 = "abc";
            Console.WriteLine(str2 + "bbb");
            Console.WriteLine(str2 + 123);
            Console.WriteLine(str2 + 123 + true);

            // 复合运算 += 
            str2 = "123";
            str2 += "5" + 4 + true;    // 先计算等号 右边
            Console.WriteLine(str2);  // 12354True

            str2 += 1 + 2 + 3 + 4;   // 先计算等号右边
            Console.WriteLine(str2);  // 12354True10

            str2 += "" + 1 + 2 + 3 + 4;
            Console.WriteLine(str2); // 12354True101234

            string str3 = "";
            str3 += 1 + 2 + "" + 3 + 4;   // 先计算等号右边的  从左往右计算
            Console.WriteLine(str3);   // 334

            // 字符串拼接第二种 Format 
            // 语法：string.Format("待拼接的内容","内容1","内容2",...)    // 相当于c语言中的printf
            // 拼接内容中的固定规则
            // 想要拼接的内容用占位符替代 {数字} 数字：0~n  依次往后
            string s = string.Format("hello {0}, my name is {1}, i am {2} years old", "lili", "leiming", 19);
            Console.WriteLine(s);

            // 控制台打印
            Console.WriteLine("hello {0}, my name is {1}, i am {2} years old", "lili", "leiming", 19);  // WriteLine\Write支持Format方法
            #endregion

            #region 条件运算符
            // >    <    ==    !=       >=      <=
            // 大于 小于 等于   不等于   大于等于 小于等于

            // 1 < a < 6 // 在c#中不能这样写，基本大部分编程语言都不能这样写

            #endregion

            #region 逻辑运算符
            // 逻辑与  &&
            // 规则：对两个bool值进行逻辑运算  有假则假  同真为真

            Console.WriteLine(true && false);

            Console.WriteLine(3>1 && 1<2);

            // 逻辑运算符优先级 低于 条件运算符、算术运算符

            // 逻辑或 ||
            // 规则：有真则真，同假为假
            Console.WriteLine(true || false);

            Console.WriteLine(3 > 1 || 1 < 2);

            Console.WriteLine(5 < 2 || 3 > 9);

            // 逻辑非 ！
            // 规则：对bool值进行取反， 真变假  假变真
            // 逻辑非的优先级 较高
            //bool b = !3 > 2;  // 报错
            bool b = !(3>2);
            Console.WriteLine(b);


            // 混合使用 优先级的问题
            // 规则：!(逻辑非)优先级最高     &&(逻辑与)优先级大于||(逻辑或)
            // 逻辑运算符优先级 低于 算术运算符 、条件运算符（逻辑非除外）


            // 逻辑运算符的短路规则
            // 只要 逻辑与或者逻辑或 左边满足了条件  右边的内容已经不重要了，可能不会去计算了
            bool result = false;
            int i3 = 1;

            result = i3 > 0 || ++i3 >= 1;  // 左边的已经为真了，右边的就不去运行了
            Console.WriteLine(i3);   // 1

            result = i3 < 0 && i3++ > 1;  // 这种，右边的也不去运行计算了
            Console.WriteLine(i3);

            #endregion

            #region 位运算符
            // 位运算符  主要用数值类型进行计算的
            // 将数值转换为2进制 再进行位运算

            // 位与 & 
            // 规则： 连接两个数值进行位计算  将数值转换成二进制
            // 对位运算 有0则0
            int x = 1;
            int y = 5;
            int z = x & y;

            //   001        ===> 1
            // & 101        ===> 5
            //   001

            Console.WriteLine(z);  // 1

            // 位或 |
            // 规则： 对位运算，有1则1
            z = x | y;
            //   001        ===> 1
            // | 101        ===> 5
            //   101
            Console.WriteLine(z);

            // 异或 ^
            // 对位运算  相同为0 不同为1
            z = x ^ y;
            //   001        ===> 1
            // ^ 101        ===> 5
            //   100
            Console.WriteLine(z);

            // 位取反 ~
            // 写在数值前面， 对位运算，0变1  1变0
            int k = ~y;
            // ~ 0000 0000 0000 0000 0000 0000 0000 0101        ===> 5
            //   1111 1111 1111 1111 1111 1111 1111 1010
            // 位取反要看什么类型，int是4个字节32位的要全部写出来整体取反，然后负数的话要用到反码补码
            Console.WriteLine(k);

            // 左移 <<   和右移 >>
            // 左移几位 右侧加几个0
            int m = 5;
            k = m << 5;
            // 10100000    移5位多5个0
            Console.WriteLine(k);
            

            // 右移几位  右侧去掉几个位数
            m = 5;  // 101
            k = m >> 2;
            // 001(01)    01就会丢掉了
            Console.WriteLine(k);


            #endregion


            #region 三目运算符
            // 空位               ? 空位                       : 空位;
            // bool类型           ? bool类型为真返回的内容      : bool类型为假返回的内容
            int q = 5;
            //str2 = q > 1 ? "q大于1" : "q不满足条件";
            str2 = q < 1 ? "q大于1" : "q不满足条件";
            Console.WriteLine(str2);
            #endregion

            #region 条件分支语句
            // if语句
            // if...else...
            // if...else if...else
            // switch语句
            // switch(变量)
            // {
            //    变量 == 常量 执行 case 和 break 之间的代码
            //    case 常量:
            //         满足条件执行的代码逻辑;
            //         break;
            //    case 常量:
            //         满足条件执行的代码逻辑;
            //         break;
            //    ......
            //    default:
            //         如果上面case的条件都不满足 就会执行 default 中的代码;
            //         break;
            // }
            // 注意：常量-->只能写一个值，不能写一个范围，不能写条件运算符 逻辑运算符
            switch (a)
            {
                case 1:
                    Console.WriteLine("1");
                    break;
                case 2:
                    Console.WriteLine("2");
                    break;
                default:
                    Console.WriteLine("100");
                    break;
            }

            // default可省略
            string kk = "123";
            switch (kk)
            {
                case "234":
                    Console.WriteLine("1");
                    break;
                case "123":
                    Console.WriteLine("2");
                    break;
            }

            // 自定义常量
            char c = 'a';
            const char cc = 'c';
            switch (c)
            {
                case cc:
                    Console.WriteLine("1");
                    break;
                default:
                    Console.WriteLine("2");
                    break;
            }

            // 贯穿
            int aa = 1;
            switch (aa)
            {
                case 1:
                case 2:
                    Console.WriteLine("1");
                    break;
                default:
                    break;
            }

            switch (aa)
            {
                case 1:
                case 2:
                    // case和break之间可以写n条语句
                    // 可以嵌套很多之前的语句
                    Console.WriteLine("mm");
                    Console.WriteLine("cc");
                    Console.WriteLine("kk");
                    Console.WriteLine("bb");
                    if (aa == 1)
                    {
                        switch (kk)
                        {
                            default:
                                break;
                        }
                    } 
                    else
                    {
                        Console.WriteLine("MM");
                    }
                    break;
                default:
                    break;
            }
            #endregion

            #region 循环语句
            // while循环
            //while (bool类型的值)
            //{
            //}
            //while (true)
            //{
            //}
            // 流程控制关键词
            // break 跳出循环
            int i = 0;
            while (true)
            {
                i++;
                Console.WriteLine(i);
                if (i == 5)
                {
                    break;
                }
            }
            Console.WriteLine(i);

            // continue 回到循环开始继续执行
            while (i < 100)
            {
                i++;
                if (i % 5 == 0)
                {
                    continue;
                }
                Console.WriteLine(i);
            }
            

            // do while 循环
            // 会先执行一次循环语句块中的逻辑，再判断是否继续
            do
            {
                Console.WriteLine(1);
            }while (i<10);

            // for循环
            // 语法： for(/*初始表达式*/， /*条件表达式*/, /*增量表达式*/) {
            //          
            //        }
            // 第一个空（初始表达式）：一般声明一个临时变量，用来计数用
            // 第二个空（条件表达式）：表面进入循环的条件， 一个bool类型的结果（bool变量 条件运算发 逻辑运算符）
            // 第三个空（增量表达式）：用第一个空中的变量 进行 自增减运算

            // 上面定义过 i 了，这里不能再定义了
            // 第一次进入循环时 才会调用第一个空中的代码
            // 每次进入循环之前，都会判断第二个空中条件，满足才会进入循环逻辑
            for(int j = 0; j < 10; j++)
            {
                Console.WriteLine(i);
                // 执行万循环语句块中的逻辑后，最后执行第三个空中的代码
            }

            // 每个空位 可以按照规则进行书写
            // 第一个空位 就是声明变量，可以连续声明
            // 第二个空位 就是进入条件，只有是bool结果的表达式都行
            // 第三个空位 就是执行一次循环逻辑过后要做的事情，多个式子都行
            for(int j = 0, t = 0;j < 10 && t < 5; ++j, t = t + 1)
            {

            }

            // 特殊写法
            //for ( ; ; )
            //{
            //    Console.WriteLine("for循环的死循环");
            //}

            int t = 0;
            for (; t < 10;)
            {

                ++t;
            }

            for (int j = 0; ; ++j)
            {
                // 判断条件提出来
                if( j >= 10)
                {
                    break;
                }
            }

            // for循环和while循环对比
            // for循环一般用来可以准确得到一个范围中的所有数
            // 相互都能实现相同的功能，可以相互转换
            #endregion
        }
    }
}
